package com.twb.auth.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.twb.auth.dataScope.enums.OrgType;
import com.twb.auth.entity.twbOrganization.TwbOrganization;
import com.twb.auth.entity.twbOrganization.TwbOrganizationResource;
import com.twb.auth.entity.twbOrganization.dto.GetTwbOrganizationByIdDto;
import com.twb.auth.entity.twbOrganization.dto.SearchTwbOrganizationDto;
import com.twb.auth.entity.twbOrganization.dto.SearchTwbOrganizationTreeDto;
import com.twb.auth.entity.twbOrganization.dto.TwbOrganizationDto;
import com.twb.auth.entity.twbOrganization.vo.SaveTwbOrganizationVo;
import com.twb.auth.entity.twbOrganization.vo.SearchTwbOrganizationTreeVo;
import com.twb.auth.entity.twbOrganization.vo.SearchTwbOrganizationVo;
import com.twb.auth.entity.twbResource.TwbResource;
import com.twb.auth.entity.twbTenantInfo.TwbTenantInfo;
import com.twb.auth.mapper.TwbOrganizationMapper;
import com.twb.auth.mapper.TwbTenantInfoMapper;
import com.twb.auth.service.ITwbOrganizationService;
import com.twb.auth.service.ITwbResourceService;
import com.twb.core.base.entity.BaseLoginUser;
import com.twb.core.base.entity.TwbPageInfo;
import com.twb.core.base.service.impl.BaseService;
import com.twb.core.constants.TwbConstants;
import com.twb.core.exception.ServiceException;
import com.twb.core.util.BeanUtils;
import com.twb.core.util.TwbPageUtil;

/**
 * @ClassName TwbOrganizationService
 * @Description 机构部门service
 * @author DSY
 * @date 2018年11月6日 下午4:25:07
 */
@Service("twbOrganizationService")
public class TwbOrganizationService extends BaseService<TwbOrganizationMapper, TwbOrganization> implements ITwbOrganizationService {

	@Autowired
	TwbOrganizationMapper twbOrganizationMapper;
	@Autowired
	ITwbResourceService twbResourceService;
	@Autowired
	TwbTenantInfoMapper twbTenantInfoMapper;

	@Override
	public Set<TwbOrganization> listOrganizationByUserId(String userId) {
		// TODO Auto-generated method stub
		return twbOrganizationMapper.listOrganizationByUserId(userId);
	}

	@Override
	public TwbPageInfo<SearchTwbOrganizationDto> searchTwbOrganization(SearchTwbOrganizationVo vo) {
		BaseLoginUser loginUser = getLoginUser();
		String parentId = vo.getParentOrgId();
		//如果parentId为空，则默认传递当前登录用户所属租户的组织机构ID
		if(StringUtils.isBlank(parentId)) {
			if (!loginUser.isDeveloper()) {
				String tenantId = loginUser.getTenantId();
				if (StringUtils.isNotBlank(tenantId)) {
					TwbTenantInfo tenantInfo = twbTenantInfoMapper.selectById(tenantId);
					parentId = tenantInfo.getOrgId();
				}
			}
		}
		
		if (StringUtils.isNotBlank(parentId) && vo.getIsAllChildNode()) {
			TwbOrganization twbOrganization = this.getById(parentId);
			vo.setSearchKey(twbOrganization.getSearchKey());
		}
		TwbPageUtil.startPage(vo);
		List<SearchTwbOrganizationDto> list = twbOrganizationMapper.searchTwbOrganization(vo);
		return TwbPageUtil.of(list);
	}

	@Override
	public List<SearchTwbOrganizationTreeDto> searchTwbOrganizationTree(SearchTwbOrganizationTreeVo vo) {

		BaseLoginUser loginUser = getLoginUser();
		if (!loginUser.isDeveloper()) {
			String tenantId = loginUser.getTenantId();
			if (StringUtils.isNotBlank(tenantId)) {
				TwbTenantInfo tenantInfo = twbTenantInfoMapper.selectById(tenantId);

				TwbOrganization twbOrganization = this.getById(tenantInfo.getOrgId());

				vo.setSearchKey(twbOrganization.getSearchKey());

			}else {
				return null;
			}
		}
		List<SearchTwbOrganizationTreeDto> list = twbOrganizationMapper.searchTwbOrganizationTree(vo);
		return list;
	}

	@Override
	public GetTwbOrganizationByIdDto getTwbOrganizationById(String id) {
		// TODO Auto-generated method stub
		return twbOrganizationMapper.getTwbOrganizationById(id);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public String saveTwbOrganization(SaveTwbOrganizationVo vo) {
		TwbOrganization checkOrg = new TwbOrganization();
		checkOrg.setCode(vo.getCode());
		checkOrg.setIsdel(0);
		long count = this.count(checkOrg);
		if (count > 0) {
			throw new ServiceException("机构编码[" + vo.getCode() + "]已存在");
		}

		if (null == vo.getOrgSeq()) {
			Integer orgSeq = twbOrganizationMapper.getMaxSeqByParentOrgId(vo.getParentOrgId());
			if (null == orgSeq) {
				orgSeq = 1;
			} else {
				orgSeq = orgSeq + 1;
			}
			vo.setOrgSeq(orgSeq);
		}
		String id = getUUID();
		TwbOrganization record = new TwbOrganization();
		record.setId(id);
		BeanUtils.copyNotNullProperties(vo, record);

		String searchKeyStr = getSearchKey(vo.getParentOrgId());

		record.setSearchKey(searchKeyStr);

		/*
		 * if (StringUtils.isNotBlank(vo.getParentOrgId())) { TwbOrganization parentOrg = get(vo.getParentOrgId());
		 * 
		 * record.setEntId(parentOrg.getEntId()); }
		 */
		String tenantId = vo.getTenantId();
		if (StringUtils.isEmpty(tenantId)) {
			TwbOrganization parentOrg = this.getById(record.getParentOrgId());
			if (parentOrg != null) {
				tenantId = parentOrg.getTenantId();
			} else {
				tenantId = TwbConstants.DEFAULT_TENANTID;
			}
		}

		record.setTenantId(tenantId);
		this.setCreateInfo(record);
		boolean result = this.save(record);
		if (result) {
			return id;
		} else {
			return null;
		}
	}

	/**
	 * @Title getSearchKey
	 * @Description 获取组织机构的SearchKey
	 * @return
	 * @author DSY
	 * @date 2020年7月8日 上午8:59:45
	 */
	private String getSearchKey(String pid) {
		Long maxSearchKey = twbOrganizationMapper.getMaxSearchKeyByParentOrgId(pid);
		String searchKeyStr = "";

		TwbOrganization parentOrg = this.getById(pid);
		String parentSearchKey = "";
		String parentLastSearchKey = "";
		if (parentOrg != null) {
			parentLastSearchKey = parentSearchKey = parentOrg.getSearchKey();

			if (StringUtils.isNotBlank(parentLastSearchKey)) {
				parentLastSearchKey = parentLastSearchKey.substring(0, parentLastSearchKey.length() - 1);

				if (parentLastSearchKey.lastIndexOf(".") > -1) {
					parentLastSearchKey = parentLastSearchKey.substring(parentLastSearchKey.lastIndexOf(".") + 1, parentLastSearchKey.length());
				}
			}
		}

		if (maxSearchKey == null || maxSearchKey == 0) {
			if (StringUtils.isNotBlank(parentLastSearchKey)) {
				searchKeyStr = parentLastSearchKey + "0001";
			} else {
				searchKeyStr = "1000";
			}
		} else {
			searchKeyStr = (++maxSearchKey).toString();
		}

		if (StringUtils.isNotBlank(parentSearchKey)) {
			searchKeyStr = parentSearchKey + searchKeyStr;
		}

		searchKeyStr += ".";

		return searchKeyStr;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean deleteTwbOrganizationById(String id) {
		TwbOrganization twbOrganization = this.getById(id);
		if (null == twbOrganization) {
			throw new ServiceException("4001", "组织机构不存在");
		}
		// 判断该机构下是否存在用户，如果存在，不允许删除
		int userCount = twbOrganizationMapper.getUserCountByOrgId(id);
		if (userCount > 0) {
			throw new ServiceException("4002", "该组织机构存在用户信息，不允许删除");
		}
		// 判断该机构下是否存在角色，如果存在，不允许删除
		int roleCount = twbOrganizationMapper.getRoleCountByOrgId(id);
		if (roleCount > 0) {
			throw new ServiceException("4003", "该组织机构存在角色信息，不允许删除");
		}
		// 判断该机构下是否存在子部门，如果存在，不允许删除
		int orgCount = twbOrganizationMapper.getChildOrgCountByOrgId(id);
		if (orgCount > 0) {
			throw new ServiceException("4004", "该组织机构存在子级组织机构信息，不允许删除");
		}
		// 删除机构下的资源信息
		twbOrganizationMapper.deleteResourceByOrgId(id);
		// 删除机构信息
		return this.removeById(id);
	}

	@Override
	public List<String> listChildrenOrgIds(String parentId) {
		TwbOrganization record = new TwbOrganization();
		record.setIsdel(0);
		List<String> ids = new ArrayList<String>();
		List<TwbOrganization> allList = this.list(record);
		getChildrenOrgIds(ids, allList, parentId);
		return ids;
	}

	/**
	 * @Title getChildrenOrgIds
	 * @Description 递归获取部门下的子部门Id
	 * @param ids
	 * @param allList
	 * @param parentId
	 * @author DSY
	 * @date 2018年11月15日 下午5:03:49
	 */
	private void getChildrenOrgIds(List<String> ids, List<TwbOrganization> allList, String parentId) {
		List<TwbOrganization> tempList = new ArrayList<TwbOrganization>(allList);
		for (TwbOrganization org : allList) {
			if (StringUtils.isNotBlank(parentId) && parentId.equals(org.getParentOrgId())) {
				ids.add(org.getId());
				tempList.remove(org);
				getChildrenOrgIds(ids, tempList, org.getId());
			}
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public int saveOrgResource(String orgId, String resIds) {
		TwbOrganization twbOrg = this.getById(orgId);
		if (twbOrg == null) {
			throw new ServiceException("机构" + orgId + "未找到");
		}
		twbOrganizationMapper.deleteResourceByOrgId(orgId);
		String[] ids = resIds.split(",");
		int result = 0;
		for (String resId : ids) {
			TwbResource twbResource = twbResourceService.getById(resId);
			if (twbResource == null) {
				throw new ServiceException("资源" + resId + "未找到");
			}

			TwbOrganizationResource orgResource = new TwbOrganizationResource();
			orgResource.setOrgId(orgId);
			orgResource.setResourceId(resId);
			result = result + twbOrganizationMapper.saveOrgResource(orgResource);
		}

		return result;
	}

	@Override
	public List<TwbOrganizationDto> searchUserOrganizationTree(String userId) {
		// TODO Auto-generated method stub
		return twbOrganizationMapper.searchUserOrganizationTree(userId);
	}

	@Override
	public String getOrgParentNames(String id) {
		String rtn = "";

		TwbOrganization twbOrganization = getById(id);

		if (twbOrganization != null) {
			if (StringUtils.isNotBlank(twbOrganization.getParentOrgId())) {

				TwbOrganization organization = new TwbOrganization();

				organization.setIsdel(0);

				List<TwbOrganization> orgs = this.list(organization);
				List<TwbOrganization> parentOrgs = new ArrayList<TwbOrganization>();

				List<String> pname = new ArrayList<String>();

				this.getParentOrg(orgs, twbOrganization.getParentOrgId(), parentOrgs);
				if(!parentOrgs.isEmpty()) {
					for (TwbOrganization o : parentOrgs) {
						String name = o.getName();
						pname.add(name);
					}
				}
				pname.add(twbOrganization.getName());

				rtn = StringUtils.join(pname, "-");
			} else {
				rtn = twbOrganization.getName();
			}
		}

		return rtn;
	}

	/**
	 * @Title getPname
	 * @Description 递归获取父级节点名称
	 * @param list
	 * @param pid
	 * @author DSY
	 * @date 2020年7月16日 上午11:20:24
	 */
	private void getParentOrg(List<TwbOrganization> list, String pid, List<TwbOrganization> parentOrgs) {

		if (CollectionUtils.isNotEmpty(list)) {
			for (TwbOrganization org : list) {
				if (org.getId().equals(pid)) {
					parentOrgs.add(0, org);

					if (StringUtils.isNotBlank(org.getParentOrgId())) {

						getParentOrg(list, org.getParentOrgId(), parentOrgs);
					}
				}
			}
		}
	}

	@Override
	public boolean logicDeleteTwbOrganizationById(String id) {
		// 判断该机构下是否存在用户，如果存在，不允许删除
		int userCount = twbOrganizationMapper.getUserCountByOrgId(id);
		if (userCount > 0) {
			throw new ServiceException("4002", "该组织机构存在用户信息，不允许删除");
		}
		// 判断该机构下是否存在角色，如果存在，不允许删除
		int roleCount = twbOrganizationMapper.getRoleCountByOrgId(id);
		if (roleCount > 0) {
			throw new ServiceException("4003", "该组织机构存在角色信息，不允许删除");
		}
		// 判断该机构下是否存在子部门，如果存在，不允许删除
		int orgCount = twbOrganizationMapper.getChildOrgCountByOrgId(id);
		if (orgCount > 0) {
			throw new ServiceException("4004", "该组织机构存在子级组织机构信息，不允许删除");
		}
		// 删除机构下的资源信息
		twbOrganizationMapper.deleteResourceByOrgId(id);
		// 删除机构信息
		TwbOrganization record = this.getById(id);
		setUpdateInfo(record);
		record.setIsdel(1);
		return this.updateById(record);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public int resetSearchKey() {
		int result = 0;
		List<SearchTwbOrganizationDto> searchFirstOrganization = twbOrganizationMapper.searchFirstOrganization();

		int firstCode = 1000;
		for (SearchTwbOrganizationDto organization : searchFirstOrganization) {
			TwbOrganization record = new TwbOrganization();
			record.setId(organization.getId());
			record.setSearchKey(firstCode + ".");
			this.updateById(record);
			firstCode++;
			result++;

			this.resetChildrensSearchKey(organization.getId());
		}

		return result;
	}

	/**
	 * @Title resetChildrensSearchKey
	 * @Description 递归更新子节点
	 * @param pid
	 * @AuthorOriginally DHL
	 * @date 2021年7月19日 下午12:55:10
	 */
	private void resetChildrensSearchKey(String pid) {

		if (StringUtils.isNotBlank(pid)) {
			List<SearchTwbOrganizationDto> organizationList = twbOrganizationMapper.searchOrganizationByPid(pid);

			if (CollectionUtils.isNotEmpty(organizationList)) {
				twbOrganizationMapper.updateSearchKeyIsNull(pid);

				for (SearchTwbOrganizationDto organization : organizationList) {
					TwbOrganization record = new TwbOrganization();
					record.setId(organization.getId());

					String searchKey = this.getSearchKey(pid);

					record.setSearchKey(searchKey);

					this.updateById(record);

					this.resetChildrensSearchKey(organization.getId());
				}
			}
		}

	}

	@Override
	public TwbOrganization getDeptOfCompanyOrgId(String deptId) {
		TwbOrganization org = this.getById(deptId);
		if(org == null) {
			throw new ServiceException("组织机构不存在");
		}
		String orgType = org.getOrgType();
		if(orgType.equals(OrgType.ORG.getCode())) {//公司
			return org;
		}else {//部门
			String parentOrgId = org.getParentOrgId();
			if(parentOrgId != null) {
				return this.getDeptOfCompanyOrgId(parentOrgId);
			}
		}
		return null;
	}

	@Override
	public List<TwbOrganization> listParentOrgsById(String id) {
		TwbOrganization organization = this.getById(id);
		if(organization != null) {
			String searchKey = organization.getSearchKey();
			String firstKey = searchKey.split("\\.")[0];
			List<TwbOrganization> orgs = twbOrganizationMapper.listOrganizationBySearchKey(firstKey);
			List<TwbOrganization> parentOrgs = new ArrayList<>();
			parentOrgs.add(organization);//添加当前机构
			this.getParentOrg(orgs, organization.getParentOrgId(), parentOrgs);
			return parentOrgs;
		}
		return null;
	}
}
